-- **********************************************************
-- ** ADDON trinityfr (http://www.trinitycore.fr)
-- **********************************************************

ADDON_VERSION = "Version 2";
DEBUG_MODE    = false
local AlreadyLoad = false


-- ***********
-- ** EVENT **
-- ***********

function trinityfrC_OnLoad()
    if GetLocale() ~= "frFR" then return; end

    this:RegisterEvent("PLAYER_ENTERING_WORLD");
    this:RegisterEvent("PLAYER_LEAVING_WORLD");
    if trinityfr_Collector == nil or trinityfr_Main == nil then
        trinityfrC_PurgeCollector();
    end
    if trinityfr_Main.serveur ~= GetCVar("realmName") then
        trinityfrC_PurgeCollector();
    end
    if trinityfr_Main.realmList ~= GetCVar("realmList") then
        trinityfrC_PurgeCollector();
    end
end

function trinityfrC_OnEvent(event,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17,arg18,arg19)
    trinityfrC_Debug("Event: "..event);

    if event == "PLAYER_ENTERING_WORLD" then
        this:RegisterEvent("CHAT_MSG_MONSTER_WHISPER");
        this:RegisterEvent("CHAT_MSG_MONSTER_SAY");
        this:RegisterEvent("CHAT_MSG_MONSTER_YELL");
        this:RegisterEvent("CHAT_MSG_MONSTER_EMOTE");
        this:RegisterEvent("CHAT_MSG_RAID_BOSS_EMOTE");
        this:RegisterEvent("QUEST_LOG_UPDATE");
        this:RegisterEvent("QUEST_DETAIL");
        this:RegisterEvent("QUEST_PROGRESS");
        this:RegisterEvent("QUEST_COMPLETE");
        this:RegisterEvent("QUEST_FINISHED");
	this:RegisterEvent("GOSSIP_SHOW");

        if not AlreadyLoad then
            DEFAULT_CHAT_FRAME:AddMessage("|cffffff00<trinityfr>|r Addon "..ADDON_VERSION.." charg\195\169.");
            AlreadyLoad = true
        end
    end
    if event == "PLAYER_LEAVING_WORLD" then
        this:UnregisterEvent("CHAT_MSG_MONSTER_WHISPER");
        this:UnregisterEvent("CHAT_MSG_MONSTER_SAY");
        this:UnregisterEvent("CHAT_MSG_MONSTER_YELL");
        this:UnregisterEvent("CHAT_MSG_MONSTER_EMOTE");
        this:UnregisterEvent("CHAT_MSG_RAID_BOSS_EMOTE");
        this:UnregisterEvent("QUEST_LOG_UPDATE");
        this:UnregisterEvent("QUEST_DETAIL");
        this:UnregisterEvent("QUEST_PROGRESS");
        this:UnregisterEvent("QUEST_COMPLETE");
        this:UnregisterEvent("QUEST_FINISHED");
	this:UnregisterEvent("GOSSIP_SHOW");
    end

    if event == "CHAT_MSG_MONSTER_WHISPER" then trinityfrC_MonsterTalk("WHISPER",arg1,arg2,arg3); end
    if event == "CHAT_MSG_MONSTER_SAY" then trinityfrC_MonsterTalk("SAY",arg1,arg2,arg3); end
    if event == "CHAT_MSG_MONSTER_YELL" then trinityfrC_MonsterTalk("YELL",arg1,arg2,arg3); end
    if event == "CHAT_MSG_MONSTER_EMOTE" then trinityfrC_MonsterTalk("EMOTE",arg1,arg2,arg3); end
    if event == "CHAT_MSG_RAID_BOSS_EMOTE" then trinityfrC_MonsterTalk("BOSS",arg1,arg2,arg3); end
    if event == "QUEST_LOG_UPDATE" then trinityfrC_QuestUpdate(); end
    if event == "QUEST_DETAIL" then trinityfrC_QuestDetail(); end
    if event == "QUEST_PROGRESS" then trinityfrC_QuestProgress(); end
    if event == "QUEST_COMPLETE" then trinityfrC_QuestComplete(); end
    if event == "GOSSIP_SHOW" then trinityfrC_GossipText(); end
end


-- **********************
-- ** FONCTIONS QUETES **
-- **********************

function trinityfrC_QuestUpdate()
    for i = 1, GetNumQuestLogEntries(), 1 do
        local Titre, Level, Tag, SuggestedGroup, IsHeader, IsCollapsed, IsComplete, IsDaily = GetQuestLogTitle(i);
        if not IsHeader then
            SelectQuestLogEntry(i);

            local QuestEntry, QuestLevel = trinityfrC_GetQuestId(GetQuestLink(i));
            local QuestTitre = trinityfrC_CleanMe(trinityfrC_CleanLevel(Titre));
            local Desc, Obj  = GetQuestLogQuestText();
            local QuestObj   = trinityfrC_CleanMe(Obj);
            local QuestDesc  = trinityfrC_CleanMe(Desc);

            local PosTab = trinityfrC_GetQuestID(QuestEntry, QuestTitre, QuestObj, QuestDesc);
            if PosTab ~= nil then
                trinityfr_Collector.quetes["quete_"..PosTab].entry = QuestEntry;
            end
        end
    end
end

function trinityfrC_QuestDetail()
    local source = trinityfrC_GetQuestSource();
    if source == nil then return; end;

    local QuestTitre = trinityfrC_CleanMe(trinityfrC_CleanLevel(GetTitleText()));
    local QuestObj   = trinityfrC_CleanMe(GetObjectiveText());
    local QuestDesc  = trinityfrC_CleanMe(GetQuestText());

    local PosTab = trinityfrC_GetQuestID(0, QuestTitre, QuestObj, QuestDesc);
    if PosTab ~= nil then return; end

    trinityfr_Main.totquest = trinityfr_Main.totquest + 1;
    PosTab = trinityfr_Main.totquest;
    trinityfr_Collector.quetes["quete_"..PosTab] = {};
    trinityfr_Collector.quetes["quete_"..PosTab].titre       = QuestTitre;
    trinityfr_Collector.quetes["quete_"..PosTab].objectif    = QuestObj;
    trinityfr_Collector.quetes["quete_"..PosTab].description = QuestDesc;
    trinityfr_Collector.quetes["quete_"..PosTab].source      = source;
end

function trinityfrC_QuestProgress()
    local source = trinityfrC_GetQuestSource();
    if source == nil then return; end;
    trinityfrC_QuestUpdate();

    local QuestTitre    = trinityfrC_CleanMe(trinityfrC_CleanLevel(GetTitleText()));
    local QuestProgress = trinityfrC_CleanMe(GetProgressText());

    local PosTab = nil;
    local NbQuest = 0;
    for i = 1, trinityfr_Main.totquest, 1 do
        if trinityfr_Collector.quetes["quete_"..i] then
            if trinityfr_Collector.quetes["quete_"..i].titre == QuestTitre then
                if trinityfr_Collector.quetes["quete_"..i].entry then
                    PosTab = i;
                    NbQuest = NbQuest + 1;
                end
            end
        end
    end
    if NbQuest ~= 1 then return; end

    trinityfr_Collector.quetes["quete_"..PosTab].progression = QuestProgress;
end

function trinityfrC_QuestComplete()
    local source = trinityfrC_GetQuestSource();
    if source == nil then return; end;
    trinityfrC_QuestUpdate();

    local QuestTitre  = trinityfrC_CleanMe(trinityfrC_CleanLevel(GetTitleText()));
    local QuestReward = trinityfrC_CleanMe(trinityfrC_CleanLevel(GetRewardText()));

    local PosTab = nil;
    local NbQuest = 0;
    for i = 1, trinityfr_Main.totquest, 1 do
        if trinityfr_Collector.quetes["quete_"..i] then
            if trinityfr_Collector.quetes["quete_"..i].titre == QuestTitre then
                if trinityfr_Collector.quetes["quete_"..i].entry then
                    PosTab = i;
                    NbQuest = NbQuest + 1;
                end
            end
        end
    end
    if NbQuest ~= 1 then return; end

    trinityfr_Collector.quetes["quete_"..PosTab].reward = QuestReward;
end

function trinityfrC_GetQuestID(Entry, QuestTitre, QuestObj, QuestDesc)
    for i = 1, trinityfr_Main.totquest, 1 do
        if trinityfr_Collector.quetes["quete_"..i] then
            if trinityfr_Collector.quetes["quete_"..i].entry then
                if trinityfr_Collector.quetes["quete_"..i].entry == Entry then return i; end
            end

            if trinityfr_Collector.quetes["quete_"..i].titre == QuestTitre then
                if trinityfr_Collector.quetes["quete_"..i].objectif == QuestObj then
                    if trinityfr_Collector.quetes["quete_"..i].description == QuestDesc then
                        return i;
                    end
                end
            end
        end
    end
    return nil;
end

function trinityfrC_GetQuestSource()
    if UnitIsPlayer("npc") then return nil; end

    local cible = trinityfrC_CleanMe(UnitName("npc"));
    local source = nil;
    if UnitIsFriend("player", "npc") or UnitReaction("player", "npc") == 4 then
        local npcid = trinityfrC_GetUnitId("target");
        source = "pnj||"..cible.."||"..npcid;
    end
    return source;
end


-- *************************
-- ** FONCTIONS TEXTES IA **
-- *************************

function trinityfrC_MonsterTalk(type, arg1, arg2, arg3)
    local what = trinityfrC_CleanMe(arg1);
    local who  = trinityfrC_CleanMe(arg2);
    local lang = trinityfrC_CleanMe(arg3);
    if lang == "" then lang = "NULL"; end

    for i = 1, trinityfr_Main.tottalk, 1 do
        if trinityfr_Collector.talk["emote_"..i] then
            if trinityfr_Collector.talk["emote_"..i].type == type then
                if trinityfr_Collector.talk["emote_"..i].what == what then
                    if trinityfr_Collector.talk["emote_"..i].lang == lang then
                        return;
                    end
                end
            end
        end
    end

    trinityfr_Main.tottalk = trinityfr_Main.tottalk + 1;
    trinityfr_Collector.talk["emote_"..trinityfr_Main.tottalk] = {};
    trinityfr_Collector.talk["emote_"..trinityfr_Main.tottalk].type = type;
    trinityfr_Collector.talk["emote_"..trinityfr_Main.tottalk].who  = who;
    trinityfr_Collector.talk["emote_"..trinityfr_Main.tottalk].what = what;
    trinityfr_Collector.talk["emote_"..trinityfr_Main.tottalk].lang = lang;
end

-- ************************
-- ** FONCTION GOSSIP *****
-- ************************

function trinityfrC_GossipText()

    texte = trinityfrC_CleanMe(trinityfrC_CleanLevel(GetGossipText())); 
    if texte == nil then return nil; end
    titre = {};
    typegossip = {};
    nbTitre = GetNumGossipOptions(); 
    titre["1"],typegossip["1"],titre["2"],typegossip["2"],titre["3"],typegossip["3"],titre["4"],typegossip["4"],titre["5"],typegossip["5"],titre["6"],typegossip["6"],titre["7"],typegossip["7"],titre["8"],typegossip["8"],titre["9"],typegossip["9"],titre["10"],typegossip["10"],titre["11"],typegossip["11"],titre["12"],typegossip["12"],titre["13"],typegossip["13"],titre["14"],typegossip["14"],titre["15"],typegossip["15"],titre["16"],typegossip["16"],titre["17"],typegossip["17"],titre["18"],typegossip["18"],titre["19"],typegossip["19"],titre["20"],typegossip["20"] = GetGossipOptions();
    if typegossip["1"] == nil then    
        typegossip["1"] = "none";
    end

    gossipId = trinityfrC_GetUnitId("target");
    PosTab = trinityfr_Main.totgossip + 1;
    nbText = 0 ;
    nbTitre = GetNumGossipOptions();  
    erreurText = 0 ;
    erreurTitre = 0 ;

    for i = 1, trinityfr_Main.totgossip, 1 do
        if trinityfr_Collector.gossip["gossip_"..i] then

	    if trinityfr_Collector.gossip["gossip_"..i].GUID == gossipId then
	        trinityfrC_Debug("gossip trouver "..typegossip["1"]  );
		
	        if trinityfr_Collector.gossip["gossip_"..i].GUID == gossipId then

		    nbText = trinityfr_Collector.gossip["gossip_"..i].nbText ;
	            nbTitre = trinityfr_Collector.gossip["gossip_"..i].nbTitre ;

                    for j = 1, nbText, 1 do
		
                        if trinityfr_Collector.gossip["gossip_"..i].texte["texte_"..j] == texte then
		            trinityfrC_Debug("gossip a le meme text "..texte );
		        else
			    erreurText = erreurText + 1 ;
	                end
		    end
		    for k = 1, nbTitre, 1 do
			if titre[""..k..""] ~= nil then 
		            for l = 1, nbTitre, 1 do
                                if trinityfr_Collector.gossip["gossip_"..i].Titre["Titre_"..l] == titre[""..k..""] then
			            trinityfrC_Debug("gossip a le meme text "..titre[""..k..""] );
		                else
			            erreurTitre = erreurTitre + 1 ;
			        end
		            end
		            if erreurTitre == nbTitre then
    		                nbTitre = nbTitre + 1;
				erreurTitre = 0 ;
		                trinityfrC_Debug("Nouveau Titre "..titre[""..k..""].." "..nbTitre );
		                trinityfr_Collector.gossip["gossip_"..i].nbTitre = nbTitre ;
		                trinityfr_Collector.gossip["gossip_"..i].Titre["Titre_"..nbTitre] = titre[""..k..""];
    		            end
			end
		    end

      		    if erreurText == nbText then
    		            numText = nbText + 1;
		            trinityfrC_Debug("Nouveau text "..texte.." "..numText );
		            trinityfr_Collector.gossip["gossip_"..i].nbText = numText ;
		            trinityfr_Collector.gossip["gossip_"..i].texte["texte_"..numText] = texte;
    		    end
		    return;
                end
            end
        end
    end

    trinityfr_Main.totgossip = trinityfr_Main.totgossip + 1;
    trinityfr_Collector.gossip["gossip_"..PosTab] = {};
    trinityfr_Collector.gossip["gossip_"..PosTab].texte = {};
    trinityfr_Collector.gossip["gossip_"..PosTab].Titre = {};
    trinityfr_Collector.gossip["gossip_"..PosTab].nbText = 1;
    trinityfr_Collector.gossip["gossip_"..PosTab].nbTitre = nbTitre;
    trinityfr_Collector.gossip["gossip_"..PosTab].texte["texte_1"] = texte;
    trinityfr_Collector.gossip["gossip_"..PosTab].GUID = gossipId ;
    trinityfr_Collector.gossip["gossip_"..PosTab].type = typegossip["1"];
    for i = 1, nbTitre, 1 do
	trinityfr_Collector.gossip["gossip_"..PosTab].Titre["Titre_"..i] = titre[""..i..""] ;
    end
end

-- ************************
-- ** FONCTIONS DIVERSES **
-- ************************

function trinityfrC_CleanMe(toclean)
    if toclean == nil then return ""; end
    toclean = string.gsub(toclean, "\n", "|n|");
    toclean = string.gsub(toclean, "\r", "");
    toclean = string.gsub(toclean, "\"","dbquote");
    toclean = string.gsub(toclean, UnitName("player"), "$N");
    return toclean;
end

function trinityfrC_CleanLevel(toclean)
    local NewTitre;
    local _, _, niveau, titre = string.find(toclean, "%[(.*)%] (.*)");
    if (titre) then
        NewTitre = titre;
    else
        NewTitre = toclean;
    end
    return NewTitre;
end

function trinityfrC_PurgeCollector()
    trinityfr_Collector = {};
    trinityfr_Collector.talk = {};
    trinityfr_Collector.quetes = {};
    trinityfr_Collector.gossip = {};
    trinityfr_Main = {};
    trinityfr_Main.tottalk = 0;
    trinityfr_Main.totquest = 0;
    trinityfr_Main.totgossip = 0;
    trinityfr_Main.serveur = GetCVar("realmName");
    trinityfr_Main.realmList = GetCVar("realmList");
end

function trinityfrC_GetQuestId(quest)
    if quest == nil then return nil; end
    local questid = nil;
    local returnlvl,returnid;
    for _, id, lvl, _ in string.gmatch(quest, "|c(%x+)|Hquest:(%d+):(%-?%d+)|h%[(.+)%]|h|r") do
        returnlvl= lvl;
        returnid = id;
    end
    return returnid,returnlvl;
end

function trinityfrC_GetUnitId(unit)
    guid = UnitGUID(unit);
    id = tonumber(string.sub(guid,6,12), 16);
    return id;
end

function trinityfrC_Debug(phrase)
    if not DEBUG_MODE then return; end
    DEFAULT_CHAT_FRAME:AddMessage("|cffffff00<trinityfr>|r "..phrase);
end
